package com.github.dice.service.impl;

import java.util.List;

import javax.annotation.Nonnull;
import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.dice.constant.ErrorEnums;
import com.github.dice.dto.JoinRoomDTO;
import com.github.dice.dto.OpenRoomDTO;
import com.github.dice.dto.RoomDTO;
import com.github.dice.entity.Player;
import com.github.dice.entity.Room;
import com.github.dice.entity.RoomAndPlayerMapping;
import com.github.dice.entity.RoomOwner;
import com.github.dice.exception.BusinessException;
import com.github.dice.mapper.RoomMapper;
import com.github.dice.service.IRoomAndPlayerMappingService;
import com.github.dice.service.IRoomOwnerService;
import com.github.dice.service.IRoomService;

@Service
public class RoomService extends ServiceImpl<RoomMapper, Room> implements IRoomService {

    private Logger                       logger = LoggerFactory.getLogger(RoomService.class);

    @Resource
    private RoomMapper                   roomMapper;

    @Resource
    private IRoomOwnerService            roomOwnerService;

    @Resource
    private IRoomAndPlayerMappingService roomAndPlayerMappingService;

    public RoomDTO openRoom(OpenRoomDTO openRoomDTO) {
        RoomDTO roomDTO = new RoomDTO();
        //1. get roomOwner
        RoomOwner roomOwner = roomOwnerService.getRoomOwnerByRoomOwnerName(openRoomDTO.getRoomOwnerName());
        if (ObjectUtils.isEmpty(roomOwner)) {
            throw new BusinessException(ErrorEnums.E_6001);
        }
        //2. create room
        Room room = new Room();
        BeanUtils.copyProperties(openRoomDTO, room);
        Room addRoomResult = addRoom(room);
        //3. bind roomDTO
        BeanUtils.copyProperties(addRoomResult, roomDTO);
        roomDTO.setRoomOwner(roomOwner);
        return roomDTO;
    }

    public RoomDTO joinRoom(JoinRoomDTO joinRoomDTO) throws BusinessException {
        //1.check room pwd
        Room room = getRoomByNumber(joinRoomDTO.getRoomNumber());
        if (!StringUtils.equals(room.getRoomPwd(), joinRoomDTO.getRoomPwd())) {
            throw new BusinessException(ErrorEnums.E_4001);
        }
        //2. check room is over the limit
        RoomDTO roomDTO = getRoomDTOByRoomNumber(joinRoomDTO.getRoomNumber());
            for (Player player :roomDTO.getPlayerList()) {
                if(player.getPlayerName().equals(joinRoomDTO.getPlayerName())){
                    return roomDTO;
                }
            }
        if (roomDTO.getPlayerList().size()+1 > roomDTO.getPlayerCount()) {
            throw new BusinessException(ErrorEnums.E_4002);
        }
        //3. create roomAndPlayerMapping
        RoomAndPlayerMapping roomAndPlayerMapping = new RoomAndPlayerMapping();
        BeanUtils.copyProperties(joinRoomDTO, roomAndPlayerMapping);
        roomAndPlayerMappingService.addRoomAndPlayerMapping(roomAndPlayerMapping);
        //4. bind retrun value
        return bindRoomDTOByRoom(room);
    }

    public RoomDTO getRoomDTOByRoomNumber(@Nonnull String roomNumber) {
        //get room info
        Room room = getRoomByNumber(roomNumber);
        return bindRoomDTOByRoom(room);
    }

    /**
     * data bind RoomDTO by Room
     *
     * @param room
     * @return
     */
    private RoomDTO bindRoomDTOByRoom(Room room) {
        RoomDTO roomDTO = new RoomDTO();
        //get roomOwner info
        RoomOwner roomOwner = roomOwnerService.getRoomOwnerByRoomOwnerName(room.getRoomOwnerName());
        //get players in this room
        List<Player> players = roomAndPlayerMappingService
                .getRoomAndPlayerMappingListByRoomNumber(room.getRoomNumber());
        //7. bind roomDTO
        BeanUtils.copyProperties(room, roomDTO);
        roomDTO.setRoomOwner(roomOwner);
        roomDTO.setPlayerList(players);
        return roomDTO;
    }

    public Room getRoomByNumber(@Nonnull String roomNumber) {
        QueryWrapper<Room> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("room_number", roomNumber);
        queryWrapper.eq("is_delete", 0);
        return roomMapper.selectOne(queryWrapper);
    }

    public Room addRoom(Room room) {
        Room findRoom = getRoomByNumber(room.getRoomNumber());
        if (ObjectUtils.isEmpty(findRoom)) {
            room.setIsDelete(0);
            roomMapper.insert(room);
            return room;
        }else{
            throw new BusinessException(ErrorEnums.E_6007);
        }
    }

    public List<Room> getRoomListByRoomOwnerName(String roomOwnerName) {
        QueryWrapper<Room> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("room_owner_name", roomOwnerName);
        queryWrapper.eq("is_delete", 0);
        return roomMapper.selectList(queryWrapper);
    }

    @Override
    public void delRoom(@Nonnull String roomNumber) {
        Room findRoom = getRoomByNumber(roomNumber);
        if (!ObjectUtils.isEmpty(findRoom)) {
            Room updateRoom = new Room();
            updateRoom.setIsDelete(1);
            updateRoom.setRoomId(findRoom.getRoomId());
            roomMapper.updateById(updateRoom);
        }
    }

}
